package com.common.configuration;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONUtil;
import com.common.enums.ApiResult;
import com.common.filter.SystemDefaultAuthenticationFilter;
import com.common.filter.SystemDefaultLoginFilter;
import com.common.filter.SystemLowCodeFilter;
import com.common.handler.SystemDefaultLogoutSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.CorsConfigurer;
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.io.PrintWriter;

/**
 * @Description: spring-security核心配置
 * @Date: 2025/6/5 11:26
 */
@Configuration
@EnableWebSecurity
public class SystemSecurityConfiguration {

    @Autowired
    private SecurityRequestConfiguration securityRequestConfiguration;

    @Autowired
    private SystemDefaultLogoutSuccessHandler systemDefaultLogoutSuccessHandler;

    @Autowired
    private SystemDefaultLoginFilter systemDefaultLoginFilter;

    @Autowired
    private SystemDefaultAuthenticationFilter systemDefaultAuthenticationFilter;

    @Autowired
    private SystemLowCodeFilter systemLowCodeFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((authorize) ->
                        authorize
                                .requestMatchers(ArrayUtil.toArray(securityRequestConfiguration.getPermitAll(), String.class)).permitAll()
                                .requestMatchers(ArrayUtil.toArray(securityRequestConfiguration.getAuthenticated(), String.class)).authenticated())
                .csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable)
                //不采用spring-security提供的默认用户登陆的过滤器
                .formLogin(AbstractHttpConfigurer::disable)
                .logout(logoutConfigurer -> logoutConfigurer.logoutSuccessHandler(systemDefaultLogoutSuccessHandler))
                .addFilterAfter(systemDefaultLoginFilter, LogoutFilter.class)
                .addFilterAfter(systemDefaultAuthenticationFilter, SystemDefaultLoginFilter.class)
                .addFilterAfter(systemLowCodeFilter, SystemDefaultAuthenticationFilter.class)
                .exceptionHandling(httpSecurityExceptionHandlingConfigurer -> {
                    httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(authenticationEntryPoint());
                });
        return http.build();
    }

    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint() {
        return (request, response, authException) -> {
            int status = response.getStatus();
            ApiResult responseResult = null;
            if (404 == status) {
                responseResult = ApiResult.failure("接口不存在");
            } else {
                responseResult = ApiResult.failure("操作失败");
            }
            response.setHeader("Content-Type", "application/json;charset=UTF-8");
            PrintWriter writer = response.getWriter();
            writer.write(JSONUtil.parseObj(responseResult).toStringPretty());
            writer.flush();
            writer.close();
        };
    }
}
